/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  common_util.cpp
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/09/26
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#include "common_util.h"
#include <math.h> 
# include <stdio.h>
# include <stdlib.h>
#include<stdarg.h>
#include <core/Utility.h>
#ifdef _WINDOWS
#include <stdarg.h>
#include <process.h>
#include <signal.h>
#include <windows.h>
namespace qb{
	namespace proto{

		void DbgError(char* smt, char* file, char* func, int line, const char* format, ...)
		{
			const size_t tsize = 1024;
			const size_t assert_size = 2048;
			char buffer[tsize] = { 0 };
			char assertbuf[assert_size] = { 0 };

			memset(buffer, 0, tsize);
			memset(assertbuf, 0, assert_size*sizeof(char));

			va_list args;
			int ret;
			va_start(args, format);
			const char* pFileShort = strrchr(file, '\\');
			if (pFileShort == 0)
				pFileShort = file;
			else
				pFileShort++;

			ret = FMTBUF(buffer, "%s:%d:%s() ", pFileShort, line, func);


			ret = vsprintf_s(assertbuf, assert_size, format, args);
			memmove_s(buffer + ret, tsize - ret, assertbuf, ret);

			va_end(args);

			UINT utype = MB_ABORTRETRYIGNORE | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL;
			utype |= MB_SETFOREGROUND | MB_TOPMOST;
			const char* title = "Microsoft Visual C++ Runtime Library";
			int nCode = MessageBoxA(NULL, assertbuf, title, utype);
			if (nCode == IDABORT){
				raise(SIGABRT);
				_exit(3);
			}
			if (nCode == IDRETRY){
				DebugBreak();
				return;
			}
			if (nCode == IDIGNORE)
			{
				return;
			}
			abort();
		}
	}
}

#else
namespace qb{
	namespace proto{
		void DbgError(char* smt, char* file, char* func, int line, const char* format, ...)
		{
		}
	}
}
#endif

namespace qb{
	namespace proto{
		namespace{
			//static_assert(sizeof(u32) == 4, "sizeof(u32) must equal to 4");
			int rfill_int(unsigned int number, char* buf, int cap, int fixed)
			{
				// 将缓冲区buf从右往左填充整数,多余就以0填充
				// fixed指最多填充多少个字节,cap为buf的剩余缓冲区大小
				// 当number为24,fixed为6,那么填充为"000024",从右往左填充,不足补0
				char* ptr = buf + fixed - 1;
				char* pend = buf + cap;
				while (number > 0)
				{
					if (ptr < pend)
						*ptr = '0' + (number % 10);
					number = number / 10;
					--ptr;
				}
				while (ptr >= buf){ *ptr-- = '0'; }
				return cap > fixed ? fixed : cap;
			}
			// bit scan forward for 64 bit integral number
			/* ============================================ */
			inline int bsf_folded(ui64 bb)
			{
				// 来自:https://www.2cto.com/kf/201108/101561.html
				// 也可以用系统函数替代:_BitScanForward64(头文件未找到)
				// 原始函数有bug,当参数为0和0x8000000000000000ul时,返回值都是63
				static const int lsb_64_table[64] =
				{
					63, 30, 3, 32, 59, 14, 11, 33,
					60, 24, 50, 9, 55, 19, 21, 34,
					61, 29, 2, 53, 51, 23, 41, 18,
					56, 28, 1, 43, 46, 27, 0, 35,
					62, 31, 58, 4, 5, 49, 54, 6,
					15, 52, 12, 40, 7, 42, 45, 16,
					25, 57, 48, 13, 10, 39, 8, 44,
					20, 47, 38, 22, 17, 37, 36, 26
				};
				if (bb == 0)return 64;
				bb ^= bb - 1;
				unsigned int folded = (int)bb ^ (bb >> 32);
				return lsb_64_table[folded * 0x78291ACF >> 26];
			}
			int get_max_decimal_fraction_len(double d)
			{
				// 计算指定双精度浮点数的小数部分的有效位数
				// 该位数本身及之后的小数点都不是精确的
				// 示例 298466555.37583545234  其真实值是:298466555.375835478305816650390625
				class DoubleFractionLengthMap{
					int		m_map[53];
				public:
					DoubleFractionLengthMap()
					{
						for (int i = 0; i <= 52; i++)
						{
							int len = 0;
							double d = 1.0 / pow(2.0, i);
							while (d < 1.0){ d *= 10; len++; }
							m_map[i] = len;
						}
					}
					inline int GetLength(int index)const{ return m_map[index]; }
				};
				static DoubleFractionLengthMap fractionLenMap;

				u32* data = (u32*)&d;
				int x = ((data[1] & 0x7ff00000) >> 20) - 1023;
				ui64 num = *((ui64*)&d);
				int pos = 52 - x - bsf_folded(num);
				int len = pos <= 0 ? 0 : pos;
				return len < 20 ? len : fractionLenMap.GetLength(len);
			}

		}
		int MathUtil::itoa(int number, char* buf, int cap)
		{
			// 快速将32位整数转化为字符串
			// 性能相对于系统的_itoa_s,提升40%左右,见测试函数Test_itoa
			// 返回字符串长度
			if (buf == NULL || cap <= 1)return 0;
			int num = number;
			char* ptr = buf; char* pend = buf + cap - 1;
			if (number == 0){ *ptr++ = '0'; *ptr++ = 0; return 1; }
			if (number < 0){ number = -number; *ptr++ = '-'; }
			char* pchar = ptr;
			while (number > 0 && ptr < pend)
			{
				*ptr++ = '0' + (number % 10);
				number = number / 10;
			}
			pend = ptr - 1;
			while (pchar < pend)
			{
				char temp = *pchar;
				*pchar++ = *pend;
				*pend-- = temp;
			}
			*ptr = 0;
#ifdef ENABLE_MATH_CHECK
			ScopedBufferT<char, NewAlloctor<char>, 64> checkbuf(cap);
			::_itoa_s(num, checkbuf, cap, 10);
			BASSERTS(strcmp(buf, checkbuf) == 0, "number:%d  buf:%s checkbuf:%s", num, buf, checkbuf);
#endif
			return ptr - buf;
		}
		int MathUtil::ftoa(double number, char* buf, int cap, int maxbits)
		{
			// 快速将双精度浮点数转化为字符串
			// 性能相对于_snprintf_s,是其11倍左右
			int len = 0;
			maxbits = maxbits < 0 ? get_max_decimal_fraction_len(number) : maxbits;
			int bits = maxbits >= 9 ? 9 : maxbits;
			double part = number - ((int)number);
			while (part - ((int)part) != 0 && len < bits){ part *= 10; len++; }
			int pos = MathUtil::itoa((int)number, buf, cap);
			if (len > 0)
			{
				buf[pos] = '.'; pos++;
				int num = (part - ((int)part)) >= 0.5 ? (int)(part + 1) : (int)part;
				pos += rfill_int(num, buf + pos, cap - pos, len);
				while (cap > pos && maxbits > 9)//每次处理9个字节,2^31=2147483648,
				{
					len = 0;
					maxbits -= 9;
					bits = maxbits >= 9 ? 9 : maxbits;
					part = part - ((int)part);
					while (part - ((int)part) != 0 && len < bits){ part *= 10; len++; }
					pos += rfill_int((unsigned int)part, buf + pos, cap - pos, len);
				}
			}
			else
			{
				// 填充追加".000000"
				buf[pos] = '.'; pos++;
				pos += rfill_int(0, buf + pos, cap - pos, maxbits);
			}
#ifdef ENABLE_MATH_CHECK
			ScopedBufferT<char, NewAlloctor<char>, 64> checkbuf(cap);
			_snprintf_s(checkbuf, cap, _TRUNCATE, "%f", number);
			BASSERTS(strcmp(buf, checkbuf) == 0, "number:%f  buf:%s checkbuf:%s", number, buf, checkbuf);
#endif
			return pos;
		}
		i64 MathUtil::atoi(const char* str, int* plen)
		{
			// 只支持10进制 经过测试,是atoi的3.5~4倍
			i64 num = 0;
			if (str == NULL){ if (plen)*plen = 0; return num; }
			const char* pos = (str[0] == '-' || str[0] == '+') ? (str + 1) : str;
			while (*pos >= '0' && *pos <= '9'){ num = num * 10 + (*pos++ - '0'); }
			if (plen){ *plen = pos - str; }
			num = (str[0] == '-') ? (-num) : num;
#ifdef ENABLE_MATH_CHECK
			BASSERTS(num == ::atoi(str), "%d != ::atoi(%s):%d", num, str, ::atoi(str));
#endif
			return num;
		}
		double MathUtil::atof(const char* str)
		{
			if (str == nullptr)
				return 0;
			// atof的4.5倍
			int len = 0, n2 = 0;
			i64 n1 = MathUtil::atoi(str, &len);
			bool negative = n1 < 0 || (n1 == 0 && str != NULL && str[0] == '-');
			if (str[len] == '.')
				n2 = (int)MathUtil::atoi(str + len + 1, &len);
			double d = (n1 < 0 ? (-n1) : n1) + (n2 == 0 ? 0 : (((double)n2) / pow(10.0, len)));
#ifdef ENABLE_MATH_CHECK
			BASSERTS(fabs(d - ::atof(str)) < 0.00000001, "d:%f  ato(%s)=%f", d, str, ::atof(str));
#endif
			return negative ? (-d) : d;
		}

		int StringUtil::SplitStringInfo(const char* str, int size, const std::string& key, strinfo* strings, int capcity)
		{
			int start = 0;
			int ipos = 0;
			for (int i = 0; i < size; ++i)
			{
				if (key.find(str[i]) != std::string::npos)
				{
					if (i > start && ipos < capcity)
					{
						strinfo info; info.pos = start; info.len = i - start;
						strings[ipos++] = info;
					}
					start = i + 1;
				}
			}
			if (size > start && ipos < capcity)
			{
				strinfo info; info.pos = start; info.len = size - start;
				strings[ipos++] = info;
			}
			return ipos;
		}
	}//namespace base;
}//namespace ss;
